package com.nnnu.orange.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nnnu.orange.constant.MessageConstants;
import com.nnnu.orange.constant.StatusConstants;
import com.nnnu.orange.mapper.BooksMapper;
import com.nnnu.orange.mapper.BorrowingsMapper;
import com.nnnu.orange.mapper.ReservationsMapper;
import com.nnnu.orange.pojo.entity.Books;
import com.nnnu.orange.pojo.entity.Reservations;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 定时任务类定时审核预约管理的数据
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class ReservationsTask {
    private final ReservationsMapper reservationsMapper;
    private final BooksMapper booksMapper;



    /**
     * 定时审核预约记录
     */
    @Transactional(rollbackFor = Exception.class) // 指定回滚异常)
    @Scheduled(cron = "0 0 * * * ?")
    public void reviewReservations() {
        // 查询所有待审核预约记录
        List<Reservations> reservationsList = reservationsMapper
                .selectList(new LambdaQueryWrapper<Reservations>().eq(Reservations::getStatus, StatusConstants.ZERO));
        if (CollectionUtils.isEmpty(reservationsList)) {
            log.info("没有待审核的预约记录");
            return;
        }
        reservationsList.forEach(reservation -> {
            // 获取图书信息
            Books book = booksMapper.selectById(reservation.getBookId());
            if (book == null) {
                log.warn("预约记录中图书不存在, ID: {}", reservation.getBookId());
                reservation.setStatus(StatusConstants.TWO)
                        .setStatusReason(MessageConstants.BOOK_NOT_FOUND);
            } else if (book.getAvailableCopies() > 0) {
                // 使用乐观锁减少库存
                int affectedRows = booksMapper.reduceStockWithVersion(book.getBookId(), book.getVersion());
                if (affectedRows > 0) {
                    reservation.setStatus(StatusConstants.ONE)
                            .setStatusReason(MessageConstants.RESERVATION_SUCCESS);
                    log.info("预约成功: {}, 图书库存已更新", reservation.getReservationId());
                } else {
                    reservation.setStatus(StatusConstants.TWO)
                            .setStatusReason(MessageConstants.RESERVATION_BOOK_ERR);
                    log.warn("预约失败: {}, 库存不足", reservation.getReservationId());
                }
            } else {
                reservation.setStatus(StatusConstants.TWO)
                        .setStatusReason(MessageConstants.RESERVATION_BOOK_ERR);
                log.warn("预约失败: {}, 图书库存不足", reservation.getReservationId());
            }
            // 更新预约记录状态
            reservation.setUpdatedAt(LocalDateTime.now());
            reservationsMapper.updateById(reservation);
        });
    }


    /**
     * 修改预约状态 每天的19:30
     * 检查预约是否已在规定时间内取书，如果没有取书则取消预约。
     */
    @Scheduled(cron = "0 30 19 * * ?")
    public void updateStatus() {
        log.info("开始检查预约取书状态，当前时间：{}", LocalDateTime.now());

        // 获取所有未完成（状态为待确认）的预约记录
        List<Reservations> pendingReservations = reservationsMapper.selectList(
                new LambdaQueryWrapper<Reservations>()
                        .eq(Reservations::getStatus, StatusConstants.ZERO) // 状态为以确认
                        .lt(Reservations::getPickUpDate, LocalDateTime.now()) // 截止时间已过
        );

        if (CollectionUtils.isEmpty(pendingReservations)) {
            log.info("没有需要取消的预约记录");
            return;
        }

        // 遍历预约记录，取消未取书的预约
        pendingReservations.forEach(reservation -> {
            reservation.setStatus(StatusConstants.TWO) // 设置为取消状态
                    .setStatusReason(MessageConstants.RESERVATION_ERR)
                    .setUpdatedAt(LocalDateTime.now());
            reservationsMapper.updateById(reservation);
            log.info("预约ID {} 未按时取书，已取消", reservation.getReservationId());
        });
        log.info("预约取书状态检查完成，共处理 {} 条记录", pendingReservations.size());
    }


}
